<?php

namespace km\graphics;

class RasterImage {
	/**
	 * @var RasterImageBackend
	 */
	private $backend;
	/**
	 * @param $backend
	 * @return void
	 */
	function __construct(RasterImageBackend $backend = null)
	{
		if (null === $backend) {
			$backend = new RasterImageBackendGD();
		}
		$this->backend = $backend;
	}
	/**
	 * @return RasterImageBackend
	 */
	function getBackend()
	{
		return $this->backend;
	}
	/**
	 * @param $filename
	 * @return void
	 */
	function loadFile($filename)
	{
		return $this->backend->loadFile($filename);
	}
	/**
	 * @param string $s
	 * @return void
	 */
	function loadString($s)
	{
		return $this->backend->loadString($s);
	}
	/**
	 * @return int
	 */
	function getWidth()
	{
		return $this->backend->getWidth();
	}
	/**
	 * @return int
	 */
	function getHeight()
	{
		return $this->backend->getHeight();
	}
	/**
	 * Scale image exactly to the specified size
	 * @param int $width
	 * @param int $height
	 * @return void
	 */
	function scale($width, $height)
	{
		$this->backend->region(0, 0, $this->backend->getWidth(), $this->backend->getHeight(), $width, $height);
	}
	/**
	 * Scale to a specified width, preserving aspect ratio
	 * @param int $new_width
	 * @param bool $only_scale_down
	 * @return void
	 */
	function scaleToWidth($new_width, $only_scale_down = true)
	{
		if ($only_scale_down && ($new_width >= $this->backend->getWidth()))
		{
			return ;
		}

		$new_height = floor($this->backend->getHeight() * ($new_width / $this->backend->getWidth()));
		return $this->scale($new_width, $new_height);
	}
	/**
	 * Scale to a specified height, preserving aspect ratio
	 * @param int $new_height
	 * @param bool $only_scale_down
	 * @return void
	 */
	function scaleToHeight($new_height, $only_scale_down = true)
	{
		if ($only_scale_down && ($new_height >= $this->backend->getHeight()))
		{
			return ;
		}

		$new_width = floor($this->backend->getWidth() * ($new_height / $this->backend->getHeight()));
		return $this->scale($new_width, $new_height);
	}
	/**
	 * Scale to a specified size, preserving aspect ratio
	 * @param int $size
	 * @param bool $only_scale_down
	 * @return void
	 */
	function scaleToMaxSize($size, $only_scale_down = true)
	{
		if ($this->backend->getWidth() > $this->backend->getHeight())
		{
			return $this->scaleToWidth($size, $only_scale_down);
		} else {
			return $this->scaleToHeight($size, $only_scale_down);
		}
	}
	/**
	 * Resize image so that it is inscribed into rectangle. Thi does not create any background,
	 * the image is ONLY resized.
	 *
	 * @param int $width
	 * @param int $height
	 * @param $only_scale_down
	 * @throws GraphicsException
	 */
	function inscribe($width, $height, $only_scale_down = true)
	{
		if (($width / $height) > ($this->backend->getWidth() / $this->backend->getHeight()))
		{
			$this->scaleToHeight($height, $only_scale_down);
		} else {
			$this->scaleToWidth($width, $only_scale_down);
		}
	}
	/**
	 * Resize image so that it is inscribed into rectangle.
	 * If the resulting image size differs from $width x $height -
	 * then the margins fill be filled with background.
	 * The resulting image size will be exactly $width x $height
	 *
	 * @param int $width
	 * @param int $height
	 * @param bool $only_scale_down
	 * @param int $r 1 ... 255
	 * @param int $g 1 ... 255
	 * @param int $b 1 ... 255
	 * @param int $alpha 1 ... 127
	 * @throws GraphicsException
	 */
	function inscribeExact($width, $height, $only_scale_down = true, $r = 255, $g = 255, $b = 255, $alpha = 0)
	{
		$this->inscribe($width, $height, $only_scale_down);
		
		$backend_class = get_class($this->backend);
		$bg = new $backend_class();
		$bg->reset($width, $height, $r, $g, $b, $alpha);
		
		$x = floor(($width - $this->backend->getWidth()) / 2);
		$y = floor(($height - $this->backend->getHeight()) / 2);
		$bg->paste($this->backend, $x, $y);
		
		$this->backend = $bg;
	}
	/**
	 * Inscribe into rectangle, the margins left transparent
	 * @see RasterImage#inscribeExact($width, $height, $only_scale_down = true, $r = 255, $g = 255, $b = 255, $alpha = 0)
	 * @param int $width
	 * @param int $height
	 * @param bool $only_scale_down
	 * @throws GraphicsException
	 */
	function inscribeTransparentMargins($width, $height, $only_scale_down = true)
	{
		return $this->inscribeExact($width, $height, $only_scale_down, 0, 0, 0, 127);
	}
	function saveFile($filename)
	{
		return $this->backend->saveFile($filename);
	}
	function saveString($type)
	{
		return $this->backend->saveString($filename);
	}
}